package drone.basis.util ;

import java.math.BigDecimal ;
import java.math.BigInteger ;
import java.math.RoundingMode ;
import java.util.Objects ;
import java.util.Random ;

import org.apache.commons.lang.math.NumberUtils ;

public class NumberUtil
{

	private static final int SCALE = 2 ;

	private static final int BIGSCALE = 18 ;

	private static final String ZEROS = "00000000" ;

	private static final String NINES = "99999999" ;

	/**
	 * * 格式化 默认两位 并返回string*
	 */
	public static boolean isNumber (
			Object source
	)
	{
		if ( Objects.isNull ( source ) )
		{
			return false ;
		}

		return NumberUtils.isNumber ( source.toString ( ) ) ;
	}

	/**
	 * * 格式化 默认两位 并返回string*
	 */
	public static BigDecimal format (
			Object source
	)
	{
		if ( Objects.isNull ( source ) || StringUtil.isEmpty ( source.toString ( ) ) )
		{
			source = "0" ;
		}
		return new BigDecimal ( source.toString ( ) ) ;
	}

	/**
	 * * 格式化 默认两位 并返回string*
	 */
	public static String transfer (
			Object v1
	)
	{
		return decimal ( v1 , SCALE ).toString ( ) ;
	}

	/**
	 * * 格式化为指定位数 并返回string *
	 */
	public static String transfer (
			Object v1 ,
			int scale
	)
	{
		return decimal ( v1 , scale ).toString ( ) ;
	}

	/**
	 * * 格式化 默认两位 并返回BigDecimal*
	 */
	public static BigDecimal decimal (
			Object v1
	)
	{
		return decimal ( v1 , SCALE ) ;
	}

	/**
	 * * 格式化为指定位数 并返回BigDecimal *
	 */
	public static BigDecimal decimal (
			Object v1 ,
			int scale
	)
	{
		if ( Objects.isNull ( v1 ) || StringUtil.isEmpty ( v1.toString ( ) ) )
		{
			v1 = "0" ;
		}
		BigDecimal res = new BigDecimal ( v1.toString ( ) ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return res ;
	}

	/**
	 * * 格式化 默认两位 *
	 */
	public static Double scale (
			Object v1
	)
	{
		return scale ( v1 , SCALE ) ;
	}

	/**
	 * * 格式化为指定位数 *
	 */
	public static Double scale (
			Object v1 ,
			int scale
	)
	{
		BigDecimal res = new BigDecimal ( v1.toString ( ) ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return new Double ( res.doubleValue ( ) ) ;
	}

	/**
	 * * 两个Double数相加 默认保留两位*
	 */
	public static Double add (
			Double v1 ,
			Double v2
	)
	{
		return add ( v1 , v2 , SCALE ) ;
	}

	/**
	 * * 两个Double数相加 并保留scale位小数*
	 */
	public static Double add (
			Double v1 ,
			Double v2 ,
			int scale
	)
	{
		BigDecimal res = new BigDecimal ( v1.toString ( ) ).add ( new BigDecimal ( v2.toString ( ) ) ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return new Double ( res.doubleValue ( ) ) ;
	}

	/**
	 * * 两个Double数相减 默认保留两位*
	 */
	public static Double sub (
			Double v1 ,
			Double v2
	)
	{
		return sub ( v1 , v2 , SCALE ) ;
	}

	/**
	 * * 两个Double数相减 并保留scale位小数*
	 */
	public static Double sub (
			Double v1 ,
			Double v2 ,
			int scale
	)
	{
		BigDecimal res = new BigDecimal ( v1.toString ( ) ).subtract ( new BigDecimal ( v2.toString ( ) ) ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return new Double ( res.doubleValue ( ) ) ;
	}

	/**
	 * * 两个Double数相乘 默认保留两位*
	 */
	public static Double mul (
			Double v1 ,
			Double v2
	)
	{
		return mul ( v1 , v2 , SCALE ) ;
	}

	/**
	 * * 两个Double数相乘 并保留scale位小数 *
	 */
	public static Double mul (
			Double v1 ,
			Double v2 ,
			int scale
	)
	{
		BigDecimal res = new BigDecimal ( v1.toString ( ) ).multiply ( new BigDecimal ( v2.toString ( ) ) ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return new Double ( res.doubleValue ( ) ) ;
	}

	/**
	 * * 两个Double数相除 默认保留两位*
	 */
	public static Double div (
			Double v1 ,
			Double v2
	)
	{
		return div ( v1 , v2 , SCALE ) ;
	}

	/**
	 * * 两个Double数相除，并保留scale位小数 *
	 */
	public static Double div (
			Double v1 ,
			Double v2 ,
			int scale
	)
	{
		BigDecimal res = new BigDecimal ( v1.toString ( ) ).divide ( new BigDecimal ( v2.toString ( ) ) , scale , BigDecimal.ROUND_HALF_UP ) ;
		return new Double ( res.doubleValue ( ) ) ;
	}

	public static Long random (
			Long min ,
			Long max
	)
	{
		BigInteger res = random ( new BigInteger ( min.toString ( ) ) , new BigInteger ( max.toString ( ) ) ) ;
		return res.longValue ( ) ;
	}

	// 获得随机数,包含min和max
	public static BigInteger random (
			BigInteger min ,
			BigInteger max
	)
	{
		Random random = new Random ( ) ;
		BigInteger seed = new BigInteger ( 128 , random ) ;
		return seed.mod ( max.subtract ( min ).add ( new BigInteger ( "1" ) ) ).add ( min ) ;
	}

	/**
	 * * 转成百分制 默认两位
	 */
	public static Double percent (
			Double v1
	)
	{
		return div ( v1 , new Double ( 100 ) ) ;
	}

	/**
	 * * 转成百分制 指定小数位数
	 */
	public static Double percent (
			Double v1 ,
			int scale
	)
	{
		return div ( v1 , new Double ( 100 ) , scale ) ;
	}

	/**
	 * * 百分制倒转 默认两位
	 */
	public static Double unpercent (
			Double v1
	)
	{
		return mul ( v1 , new Double ( 100 ) ) ;
	}

	/**
	 * * 百分制倒转 指定小数位数
	 */
	public static Double unpercent (
			Double v1 ,
			int scale
	)
	{
		return mul ( v1 , new Double ( 100 ) , scale ) ;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////
	// BIGDECIMAL

	/**
	 * * 格式化 默认两位 *
	 */
	public static BigDecimal scale (
			BigDecimal v1
	)
	{
		return scale ( v1 , SCALE ) ;
	}

	/**
	 * * 格式化为指定位数 *
	 */
	public static BigDecimal scale (
			BigDecimal v1 ,
			int scale
	)
	{
		return v1.setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
	}

	/**
	 * * 两个BigDecimal数相加 默认保留18位*
	 */
	public static BigDecimal add (
			BigDecimal v1 ,
			BigDecimal v2
	)
	{
		return add ( v1 , v2 , BIGSCALE ) ;
	}

	/**
	 * * 两个BigDecimal数相加 并保留scale位小数*
	 */
	public static BigDecimal add (
			BigDecimal v1 ,
			BigDecimal v2 ,
			int scale
	)
	{
		BigDecimal res = new BigDecimal ( v1.toString ( ) ).add ( new BigDecimal ( v2.toString ( ) ) ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return res ;
	}

	/**
	 * * 两个BigDecimal数相减 默认保留18位*
	 */
	public static BigDecimal sub (
			BigDecimal v1 ,
			BigDecimal v2
	)
	{
		return sub ( v1 , v2 , BIGSCALE ) ;
	}

	/**
	 * * 两个BigDecimal数相减 并保留scale位小数*
	 */
	public static BigDecimal sub (
			BigDecimal v1 ,
			BigDecimal v2 ,
			int scale
	)
	{
		BigDecimal res = v1.subtract ( v2 ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return res ;
	}

	/**
	 * * 两个BigDecimal数相乘 默认保留18位*
	 */
	public static BigDecimal mul (
			BigDecimal v1 ,
			BigDecimal v2
	)
	{
		return mul ( v1 , v2 , BIGSCALE ) ;
	}

	/**
	 * * 两个BigDecimal数相乘 并保留scale位小数 *
	 */
	public static BigDecimal mul (
			BigDecimal v1 ,
			BigDecimal v2 ,
			int scale
	)
	{
		BigDecimal res = v1.multiply ( v2 ).setScale ( scale , BigDecimal.ROUND_HALF_UP ) ;
		return res ;
	}

	/**
	 * * 两个BigDecimal数相除 默认保留18位*
	 */
	public static BigDecimal div (
			BigDecimal v1 ,
			BigDecimal v2
	)
	{
		return div ( v1 , v2 , BIGSCALE ) ;
	}

	/**
	 * * 两个BigDecimal数相除，并保留scale位小数 *
	 */
	public static BigDecimal div (
			BigDecimal v1 ,
			BigDecimal v2 ,
			int scale
	)
	{
		BigDecimal res = v1.divide ( v2 , scale , BigDecimal.ROUND_HALF_UP ) ;
		return res ;
	}

	/**
	 * * 转成百分制 默认两位
	 */
	public static BigDecimal percent (
			BigDecimal v1
	)
	{
		return div ( v1 , new BigDecimal ( 100 ) ) ;
	}

	/**
	 * * 转成百分制 指定小数位数
	 */
	public static BigDecimal percent (
			BigDecimal v1 ,
			int scale
	)
	{
		return div ( v1 , new BigDecimal ( 100 ) , scale ) ;
	}

	/**
	 * * 百分制倒转 默认两位
	 */
	public static BigDecimal unpercent (
			BigDecimal v1
	)
	{
		return mul ( v1 , new BigDecimal ( 100 ) ) ;
	}

	/**
	 * * 百分制倒转 指定小数位数
	 */
	public static BigDecimal unpercent (
			BigDecimal v1 ,
			int scale
	)
	{
		return mul ( v1 , new BigDecimal ( 100 ) , scale ) ;
	}

	public static String precision (
			String source
	) throws Exception
	{

		if ( ! isNumber ( source ) )
		{
			throw new Exception ( "precision exception" ) ;
		}

		BigDecimal number = new BigDecimal ( source ) ;

		int scale = number.scale ( ) ;

		if ( source.indexOf ( ZEROS ) >= 0 )
		{
			scale = source.indexOf ( ZEROS ) ;
		}

		if ( source.indexOf ( NINES ) >= 0 )
		{
			scale = source.indexOf ( NINES ) ;
		}

		return number.setScale ( scale , RoundingMode.HALF_EVEN ).stripTrailingZeros ( ).toPlainString ( ) ;
	}

}
